+2005-08-14 Øyvind Kolås <pippin@gimp.org>
+
+ * babl/Makefile.am: added babl-instance.h, removed wilcard from
+ EXTRA_DIST
+ * babl/babl-classes.h: added BablModel **model to BablPixelFormat,
+ renamed BablReferenceFish to BablFishReference. Moved some logic out
+ to babl-instance.h.
+ * babl/babl-instance.h: new file.
+ * babl/babl-db.h: include babl-instance instead of babl-classes to
+ reduce amount of headers included by headers.
+ * babl/babl-fish.c: Added code to make it work for type conversions
+ * babl/babl-fish.h: Added babl_fish (source, destination) prototype
+ * babl/babl-internal.h: reindentation, include babl-conversion.h
+ * babl/babl-pixel-format.c: add model for each band
+ * babl/babl.c: destroy all fishes at finish
+
2005-08-14 Øyvind Kolås <pippin@gimp.org>
* babl/babl-base/Makefile.am: LDADD = -lm
int dst_bit_pitch[],
int n);
+/* magic number used at the start of all babl objects, used to do
+ * differentiation in polymorphic functions. (as well as manual
+ * type check assertions).
+ */
+#define BABL_MAGIC 0xbAb10000
+
typedef enum {
- BABL_INSTANCE = 0xBAB10000,
- BABL_TYPE,
+ BABL_INSTANCE = BABL_MAGIC,
+ BABL_TYPE,
BABL_SAMPLING,
BABL_COMPONENT,
BABL_MODEL,
BablConversion **to; /*< NULL terminated list of conversions to class */
int planar;
int bands;
+ BablModel **model;
BablComponent **component;
BablType **type;
BablSampling **sampling;
typedef struct
{
BablFish fish;
+ BablConversion **from; /*< these are here for a later stage, when calculated*/
+ BablConversion **to; /*< reference conversions can be used for "segment" */
+ /*< conversions where no other conversions exist. */
BablConversion *type_to_double;
BablConversion *model_to_rgba;
BablConversion *rgba_to_model;
BablConversion *double_to_type;
-} BablReferenceFish;
+} BablFishReference;
typedef union
{
BablPixelFormat pixel_format;
BablConversion conversion;
BablFish fish;
- BablReferenceFish reference_fish;
+ BablFishReference reference_fish;
BablImage image;
} Babl;
-#define BABL_IS_BABL(obj)\
-(NULL==(obj)?0:BABL_CLASS_TYPE_IS_VALID(((Babl*)(obj))->class_type))
-
-typedef int (*BablEachFunction) (Babl *entry,
- void *data);
-
-const char *babl_class_name (BablClassType klass);
-
-
-
-#define BABL_DEFINE_CLASS(TypeName, type_name) \
- \
-void type_name##_init (void); \
-void type_name##_destroy (void); \
-void type_name##_each (BablEachFunction each_fun, \
- void *user_data); \
-TypeName * type_name (const char *name); \
-TypeName * type_name##_id (int id); \
-TypeName * type_name##_new (const char *name, \
- ...);
-
+#define BABL_IS_BABL(obj) \
+(NULL==(obj)?0: \
+ BABL_CLASS_TYPE_IS_VALID(((Babl*)(obj))->class_type) \
+)
-#define BABL_DEFINE_CLASS_NO_NEW_NO_ID(TypeName, type_name) \
- \
-void type_name##_init (void); \
-void type_name##_destroy (void); \
-void type_name##_each (BablEachFunction each_fun, \
- void *user_data);
+#include "babl-instance.h"
#endif
#define BABL_CONVERSION_H
#include "babl-classes.h"
+
BABL_DEFINE_CLASS(BablConversion, babl_conversion)
#endif
#error babl-internal.h must be included before babl-db.h, babl-db.h is strictly internal to babl core classes.
#endif
-#include "babl-classes.h"
+#include "babl-instance.h"
#include <string.h>
#include <string.h>
#include <stdarg.h>
+#include "babl-type.h"
+#include "babl-model.h"
+
static int
each_babl_fish_destroy (Babl *babl,
void *data)
}
BablFish *
-babl_fish_new (const char *name,
- Babl *source,
- Babl *destination)
+babl_fish_new (Babl *source,
+ Babl *destination)
{
- Babl *self = NULL;
+ Babl *babl = NULL;
assert (BABL_IS_BABL (source));
assert (BABL_IS_BABL (destination));
- self = babl_calloc (sizeof (BablFish), 1);
- self->class_type = BABL_FISH;
- self->instance.id = 0;
- self->instance.name = "Fishy";
- self->fish.source = (union Babl*)source;
- self->fish.destination = (union Babl*)destination;
+ babl = babl_calloc (sizeof (BablFish), 1);
+ babl->class_type = BABL_FISH;
+ babl->instance.id = 0;
+ babl->instance.name = "Fishy";
+ babl->fish.source = (union Babl*)source;
+ babl->fish.destination = (union Babl*)destination;
- if (db_insert (self) == self)
+ if (db_insert (babl) == babl)
{
- return (BablFish*)self;
+ return (BablFish*)babl;
}
else
{
- each_babl_fish_destroy (self, NULL);
+ each_babl_fish_destroy (babl, NULL);
return NULL;
}
* is a possibility , or even full single line serialization of
* components with types.
*
- babl_add_ptr_to_list ((void ***)&(source->type.from), self);
- babl_add_ptr_to_list ((void ***)&(destination->type.to), self);
+ babl_add_ptr_to_list ((void ***)&(source->type.from), babl);
+ babl_add_ptr_to_list ((void ***)&(destination->type.to), babl);
*/
- return (BablFish*)self;
+ return (BablFish*)babl;
+}
+
+typedef struct SearchData
+{
+ Babl *source;
+ Babl *destination;
+ BablConversion *result;
+} SearchData;
+
+static int
+find_conversion (Babl *babl,
+ void *user_data)
+{
+ SearchData *sd = user_data;
+
+ if ((Babl*)babl->conversion.source == sd->source &&
+ (Babl*)babl->conversion.destination == sd->destination)
+ {
+ sd->result = (BablConversion*)babl;
+ return 1;
+ }
+ return 0;
+}
+
+BablConversion *babl_conversion_find (Babl *source,
+ Babl *destination)
+{
+ SearchData data;
+ data.source = source;
+ data.destination = destination;
+ data.result = NULL;
+ babl_conversion_each (find_conversion, &data);
+
+ if (!data.result)
+ {
+ babl_log ("%s('%s', '%s'): failed", __FUNCTION__,
+ source->instance.name, destination->instance.name);
+ return NULL;
+ }
+ return data.result;
+}
+
+BablFish *
+babl_fish_reference_new (Babl *source,
+ Babl *destination)
+{
+ Babl *babl = NULL;
+
+ assert (BABL_IS_BABL (source));
+ assert (BABL_IS_BABL (destination));
+
+ babl = babl_calloc (sizeof (BablFishReference), 1);
+ babl->class_type = BABL_FISH_REFERENCE;
+ babl->instance.id = 0;
+ babl->instance.name = "Fishy";
+ babl->fish.source = (union Babl*)source;
+ babl->fish.destination = (union Babl*)destination;
+
+ babl->reference_fish.type_to_double =
+ babl_conversion_find (
+ (Babl*)source->pixel_format.type[0],
+ (Babl*)babl_type_id (BABL_DOUBLE)
+ );
+
+ babl->reference_fish.model_to_rgba =
+ babl_conversion_find (
+ (Babl*)source->pixel_format.model[0],
+ (Babl*)babl_model_id (BABL_RGBA)
+ );
+
+ babl->reference_fish.rgba_to_model =
+ babl_conversion_find (
+ (Babl*)babl_model_id (BABL_RGBA),
+ (Babl*)destination->pixel_format.model[0]
+ );
+
+ babl->reference_fish.double_to_type =
+ babl_conversion_find (
+ (Babl*)babl_type_id (BABL_DOUBLE),
+ (Babl*)destination->pixel_format.type[0]
+ );
+
+ if (db_insert (babl) == babl)
+ {
+ return (BablFish*)babl;
+ }
+ else
+ {
+ each_babl_fish_destroy (babl, NULL);
+ return NULL;
+ }
+
+/* Might make sense to allow a precalculated shortcut to
+ * participate in later checks for optimal conversions, then we
+ * should also have better generated names,. model + datatype
+ * is a possibility , or even full single line serialization of
+ * components with types.
+
+ babl_add_ptr_to_list ((void ***)&(source->type.from), babl);
+ babl_add_ptr_to_list ((void ***)&(destination->type.to), babl);
+ */
+ return (BablFish*) babl;
+}
+
+BablFish *
+babl_fish (Babl *source,
+ Babl *destination)
+{
+ return babl_fish_reference_new (source, destination);
+}
+
+void *fooA;
+void *fooB;
+void *fooC;
+
+int
+babl_fish_process (BablFish *babl_fish,
+ void *source,
+ void *destination,
+ int n)
+{
+ Babl *babl;
+
+ fooA = malloc(1000);
+ fooB = malloc(1000);
+ fooC = malloc(1000);
+
+ assert (source);
+ assert (destination);
+
+ babl = (Babl *)babl_fish;
+ if (BABL_IS_BABL (source) ||
+ BABL_IS_BABL (destination))
+ {
+ babl_log ("%s(%p, %p, %p, %i): not handling BablImage yet",
+ __FUNCTION__, babl_fish, source, destination, n);
+ return -1;
+ }
+
+ ((BablConversion*)(babl->reference_fish.type_to_double))->function.linear(
+ source,
+ fooA,
+ n* ((BablPixelFormat*)(babl_fish->source))->bands
+ );
+ /* calculate planar representation of fooA, and fooB */
+ /* transform fooA into fooB fooB is rgba double */
+ /* calculate planar representation of fooC */
+ /* transform fooB into fooC fooC is ???? double */
+
+ ((BablConversion*)(babl->reference_fish.double_to_type))->function.linear(
+ fooA, destination, n * ((BablPixelFormat*)(babl_fish->destination))->bands
+ );
+
+ return 0;
}
-BABL_CLASS_TEMPLATE(BablFish, babl_fish, "BablFish")
+/*BABL_CLASS_TEMPLATE(BablFish, babl_fish, "BablFish")*/
+BABL_DEFINE_INIT(babl_fish)
+BABL_DEFINE_DESTROY(babl_fish)
+BABL_DEFINE_EACH(babl_fish)
BablFish *
babl_fish_new (Babl *source,
Babl *destination);
-
+
+BablFish *
+babl_fish (Babl *source,
+ Babl *destination);
+
/* babl_fish_process will probably be a polymorph function
* accepting source and destination buffer pointers will be
* allowed as well as BablImage objects in their place
babl_free (babl->pixel_format.component);
babl_free (babl->pixel_format.type);
babl_free (babl->pixel_format.sampling);
+ babl_free (babl->pixel_format.model);
babl_free (babl->instance.name);
babl_free (babl);
int id,
int planar,
int bands,
- BablComponent **band_component,
- BablSampling **band_sampling,
- BablType **band_type)
+ BablModel **model,
+ BablComponent **component,
+ BablSampling **sampling,
+ BablType **type)
{
Babl *self;
int band;
self->pixel_format.bands = bands;
self->pixel_format.planar = planar;
+ self->pixel_format.model = babl_malloc (sizeof (BablModel*) * (bands+1));
self->pixel_format.component = babl_malloc (sizeof (BablComponent*) * (bands+1));
- self->pixel_format.type = babl_malloc (sizeof (BablType*) * (bands+1));
- self->pixel_format.sampling = babl_malloc (sizeof (BablSampling*) * (bands+1));
+ self->pixel_format.type = babl_malloc (sizeof (BablType*) * (bands+1));
+ self->pixel_format.sampling = babl_malloc (sizeof (BablSampling*) * (bands+1));
for (band=0; band < bands; band++)
{
- self->pixel_format.component[band] = band_component[band];
- self->pixel_format.type[band] = band_type[band];
- self->pixel_format.sampling[band] = band_sampling[band];
+ self->pixel_format.model[band] = model[band];
+ self->pixel_format.component[band] = component[band];
+ self->pixel_format.type[band] = type[band];
+ self->pixel_format.sampling[band] = sampling[band];
}
+ self->pixel_format.model[band] = NULL;
self->pixel_format.component[band] = NULL;
self->pixel_format.type[band] = NULL;
self->pixel_format.sampling[band] = NULL;
int id = 0;
int planar = 0;
int bands = 0;
- BablComponent *band_component [BABL_MAX_BANDS];
- BablSampling *band_sampling [BABL_MAX_BANDS];
- BablType *band_type [BABL_MAX_BANDS];
+ BablModel *model [BABL_MAX_BANDS];
+ BablComponent *component [BABL_MAX_BANDS];
+ BablSampling *sampling [BABL_MAX_BANDS];
+ BablType *type [BABL_MAX_BANDS];
BablSampling *current_sampling = babl_sampling (1,1);
BablType *current_type = babl_type_id (BABL_U8);
- const char *arg=name;
+ BablModel *current_model = NULL;
+ const char *arg = name;
va_start (varg, name);
current_type = (BablType*) babl;
break;
case BABL_COMPONENT:
- band_component [bands] = (BablComponent*) babl;
- band_type [bands] = current_type;
- band_sampling [bands] = current_sampling;
+ if (!current_model)
+ {
+ babl_log ("%s(): no model specified before component %s",
+ __FUNCTION__, babl->instance.name);
+ }
+ model [bands] = current_model;
+ component [bands] = (BablComponent*) babl;
+ type [bands] = current_type;
+ sampling [bands] = current_sampling;
bands++;
if (bands>=BABL_MAX_BANDS)
{
- babl_log ("maximum number of bands (%i) exceeded for %s",
- BABL_MAX_BANDS, name);
+ babl_log ("%s(): maximum number of bands (%i) exceeded for %s",
+ __FUNCTION__, BABL_MAX_BANDS, name);
}
break;
case BABL_SAMPLING:
current_sampling = (BablSampling*)arg;
break;
- case BABL_INSTANCE:
case BABL_MODEL:
- babl_log ("%s(): %s not handled in pixel format yet",
- __FUNCTION__, babl_class_name (babl->class_type));
+ current_model = (BablModel*)arg;
break;
+ case BABL_INSTANCE:
case BABL_PIXEL_FORMAT:
-
case BABL_CONVERSION:
case BABL_CONVERSION_TYPE:
case BABL_CONVERSION_TYPE_PLANAR:
va_end (varg);
- self =pixel_format_new (name, id,
- planar,
- bands, band_component, band_sampling, band_type);
+ self = pixel_format_new (name, id,
+ planar,
+ bands,
+ model, component, sampling, type);
if ((BablPixelFormat*) db_insert ((Babl*)self) == self)
--- /dev/null
+#ifndef _BABL_INSTANCE_H
+#define _BABL_INSTANCE_H
+
+#include "babl-classes.h"
+typedef int (*BablEachFunction) (Babl *entry,
+ void *data);
+
+const char *babl_class_name (BablClassType klass);
+
+/* these defines are kept here to keep the typing needed in class
+ * headers to a minimum, only the ones overriding the basic api with
+ * custom ways of construction.
+ */
+#define BABL_DEFINE_CLASS(TypeName, type_name) \
+ \
+void type_name##_init (void); \
+void type_name##_destroy (void); \
+void type_name##_each (BablEachFunction each_fun, \
+ void *user_data); \
+TypeName * type_name (const char *name); \
+TypeName * type_name##_id (int id); \
+TypeName * type_name##_new (const char *name, \
+ ...);
+#define BABL_DEFINE_CLASS_NO_NEW_NO_ID(TypeName, type_name) \
+ \
+void type_name##_init (void); \
+void type_name##_destroy (void); \
+void type_name##_each (BablEachFunction each_fun, \
+ void *user_data);
+
+#endif
#include "babl-util.h"
#include "babl-memory.h"
#include "babl-classes.h"
+#include "babl-conversion.h"
#define babl_log(fmt, args...) do { \
fprintf (stdout, "babl: "); \
#define BABL_DEFINE_EACH(type_name) \
void \
type_name##_each (BablEachFunction each_fun, \
- void *user_data) \
+ void *user_data) \
{ \
db_each (each_fun, user_data); \
} \
babl_free (babl->pixel_format.component);
babl_free (babl->pixel_format.type);
babl_free (babl->pixel_format.sampling);
+ babl_free (babl->pixel_format.model);
babl_free (babl->instance.name);
babl_free (babl);
int id,
int planar,
int bands,
- BablComponent **band_component,
- BablSampling **band_sampling,
- BablType **band_type)
+ BablModel **model,
+ BablComponent **component,
+ BablSampling **sampling,
+ BablType **type)
{
Babl *self;
int band;
self->pixel_format.bands = bands;
self->pixel_format.planar = planar;
+ self->pixel_format.model = babl_malloc (sizeof (BablModel*) * (bands+1));
self->pixel_format.component = babl_malloc (sizeof (BablComponent*) * (bands+1));
- self->pixel_format.type = babl_malloc (sizeof (BablType*) * (bands+1));
- self->pixel_format.sampling = babl_malloc (sizeof (BablSampling*) * (bands+1));
+ self->pixel_format.type = babl_malloc (sizeof (BablType*) * (bands+1));
+ self->pixel_format.sampling = babl_malloc (sizeof (BablSampling*) * (bands+1));
for (band=0; band < bands; band++)
{
- self->pixel_format.component[band] = band_component[band];
- self->pixel_format.type[band] = band_type[band];
- self->pixel_format.sampling[band] = band_sampling[band];
+ self->pixel_format.model[band] = model[band];
+ self->pixel_format.component[band] = component[band];
+ self->pixel_format.type[band] = type[band];
+ self->pixel_format.sampling[band] = sampling[band];
}
+ self->pixel_format.model[band] = NULL;
self->pixel_format.component[band] = NULL;
self->pixel_format.type[band] = NULL;
self->pixel_format.sampling[band] = NULL;
int id = 0;
int planar = 0;
int bands = 0;
- BablComponent *band_component [BABL_MAX_BANDS];
- BablSampling *band_sampling [BABL_MAX_BANDS];
- BablType *band_type [BABL_MAX_BANDS];
+ BablModel *model [BABL_MAX_BANDS];
+ BablComponent *component [BABL_MAX_BANDS];
+ BablSampling *sampling [BABL_MAX_BANDS];
+ BablType *type [BABL_MAX_BANDS];
BablSampling *current_sampling = babl_sampling (1,1);
BablType *current_type = babl_type_id (BABL_U8);
- const char *arg=name;
+ BablModel *current_model = NULL;
+ const char *arg = name;
va_start (varg, name);
current_type = (BablType*) babl;
break;
case BABL_COMPONENT:
- band_component [bands] = (BablComponent*) babl;
- band_type [bands] = current_type;
- band_sampling [bands] = current_sampling;
+ if (!current_model)
+ {
+ babl_log ("%s(): no model specified before component %s",
+ __FUNCTION__, babl->instance.name);
+ }
+ model [bands] = current_model;
+ component [bands] = (BablComponent*) babl;
+ type [bands] = current_type;
+ sampling [bands] = current_sampling;
bands++;
if (bands>=BABL_MAX_BANDS)
{
- babl_log ("maximum number of bands (%i) exceeded for %s",
- BABL_MAX_BANDS, name);
+ babl_log ("%s(): maximum number of bands (%i) exceeded for %s",
+ __FUNCTION__, BABL_MAX_BANDS, name);
}
break;
case BABL_SAMPLING:
current_sampling = (BablSampling*)arg;
break;
- case BABL_INSTANCE:
case BABL_MODEL:
- babl_log ("%s(): %s not handled in pixel format yet",
- __FUNCTION__, babl_class_name (babl->class_type));
+ current_model = (BablModel*)arg;
break;
+ case BABL_INSTANCE:
case BABL_PIXEL_FORMAT:
-
case BABL_CONVERSION:
case BABL_CONVERSION_TYPE:
case BABL_CONVERSION_TYPE_PLANAR:
va_end (varg);
- self =pixel_format_new (name, id,
- planar,
- bands, band_component, band_sampling, band_type);
+ self = pixel_format_new (name, id,
+ planar,
+ bands,
+ model, component, sampling, type);
if ((BablPixelFormat*) db_insert ((Babl*)self) == self)
{
/* babl_base is destroy by the containing types */
+ babl_fish_destroy ();
babl_conversion_destroy ();
babl_pixel_format_destroy ();
babl_model_destroy ();